package log

import (
	"context"
	"errors"
	"fmt"
	"time"

	"github.com/sirupsen/logrus"
	"gorm.io/gorm/logger"
	"gorm.io/gorm/utils"
)

// Interface logger interface
// type Interface interface {
// 	LogMode(LogLevel) Interface
// 	Info(context.Context, string, ...interface{})
// 	Warn(context.Context, string, ...interface{})
// 	Error(context.Context, string, ...interface{})
// 	Trace(ctx context.Context, begin time.Time, fc func() (sql string, rowsAffected int64), err error)
// }

// 增强版适配器结构体
type LogrusGormLogger struct {
	Logger                    *logrus.Logger  // logrus实例指针
	SlowThreshold             time.Duration   // 慢查询阈值
	LogLevel                  logger.LogLevel // 日志级别
	IgnoreRecordNotFoundError bool            // 是否忽略记录未找到错误
}

func NewLogrusGormLogger(l *logrus.Logger) *LogrusGormLogger {
	return &LogrusGormLogger{
		Logger:                    l,
		SlowThreshold:             200 * time.Millisecond, // 默认慢查询阈值
		LogLevel:                  logger.Info,            // 默认日志级别
		IgnoreRecordNotFoundError: true,                   // 默认忽略未找到错误
	}
}

// 实现GORM的LogMode接口
func (l *LogrusGormLogger) LogMode(level logger.LogLevel) logger.Interface {
	return &LogrusGormLogger{
		Logger:                    l.Logger, // 保持同一日志实例
		SlowThreshold:             l.SlowThreshold,
		LogLevel:                  level,
		IgnoreRecordNotFoundError: l.IgnoreRecordNotFoundError,
	}
}

// 日志方法实现
func (l *LogrusGormLogger) Info(ctx context.Context, msg string, data ...interface{}) {
	if l.LogLevel >= logger.Info {
		l.Logger.WithContext(ctx).Infof(msg, data...)
	}
}

func (l *LogrusGormLogger) Warn(ctx context.Context, msg string, data ...interface{}) {
	if l.LogLevel >= logger.Warn {
		l.Logger.WithContext(ctx).Warnf(msg, data...)
	}
}

func (l *LogrusGormLogger) Error(ctx context.Context, msg string, data ...interface{}) {
	if l.LogLevel >= logger.Error {
		l.Logger.WithContext(ctx).Errorf(msg, data...)
	}
}

// Trace方法实现（核心方法）

func (l *LogrusGormLogger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
	if l.LogLevel <= logger.Silent {
		return
	}

	elapsed := time.Since(begin)
	sql, rows := fc()

	// 当不需要记录时提前返回（性能优化）
	if l.Logger.GetLevel() < logrus.InfoLevel && err == nil && elapsed <= l.SlowThreshold {
		return
	}

	fileLine := utils.FileWithLineNum()
	latencyMs := float64(elapsed.Nanoseconds()) / 1e6

	fields := logrus.Fields{
		"file":    fileLine,
		"latency": fmt.Sprintf("%.2fms", latencyMs),
		"rows":    rows,
		"sql":     sql,
	}

	if rows == -1 {
		fields["rows"] = "-"
	}

	logEntry := l.Logger.WithContext(ctx).WithFields(fields)

	switch {
	case err != nil && l.LogLevel >= logger.Error:
		if !(errors.Is(err, logger.ErrRecordNotFound) && l.IgnoreRecordNotFoundError) {
			logEntry.WithError(err).Error("GORM执行错误")
		}

	case elapsed > l.SlowThreshold && l.SlowThreshold != 0:
		if l.LogLevel >= logger.Warn {
			logEntry.Warnf("慢查询警告 (阈值: %v)", l.SlowThreshold)
		}

	default:
		if l.LogLevel >= logger.Info {
			logEntry.Debug("SQL查询")
		}
	}
}
